/*
** XML utilities
*/

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/types.h>

#include <apr_strings.h>
#include <apr_tables.h>
#include <apr_xml.h>

#include "xml.h"

char*
double_escape(apr_pool_t *p, const char *s)
{
	int i, j;
	/* first, count the number of extra characters */
	for (i = 0, j = 0; s[i] != '\0'; i++)
		if (s[i] == '<' || s[i] == '>')
			j += 7;
		else if (s[i] == '&')
			j += 8;
		else if (s[i] == '"')
			j += 9;

	if (j == 0)
		return apr_pstrmemdup(p, s, i);

	char *x = apr_palloc(p, i + j + 1);
	for (i = 0, j = 0; s[i] != '\0'; i++, j++)
		if (s[i] == '<') {
			memcpy(&x[j], "&amp;lt;", 8);
			j += 7;
		}
		else if (s[i] == '>') {
			memcpy(&x[j], "&amp;gt;", 8);
			j += 7;
		}
		else if (s[i] == '&') {
			memcpy(&x[j], "&amp;amp;", 9);
			j += 8;
		}
		else if (s[i] == '"') {
			memcpy(&x[j], "&amp;quot;", 10);
			j += 9;
		}
		else
			x[j] = s[i];

	x[j] = '\0';
	return x;
}


const char*
text(const apr_xml_elem* n, apr_pool_t* pool)
{
	if (n == NULL)
		return NULL;

	char *buf = NULL;
	apr_text *x = n->first_cdata.first;
	for (; x; x=x->next) {
		if (x->text) {
			if (!buf) {
				buf = apr_pstrdup(pool, x->text);
			} else {
				buf = apr_pstrcat(pool, buf, x->text, NULL);
			}
		}
	}

	return buf;
}

const char*
getAttribute(apr_xml_elem* n, char* aname)
{
	if (n == NULL)
		return NULL;

	apr_xml_attr *attr = n->attr;
	for (; attr; attr=attr->next) {
		if (!strcmp(attr->name, aname))
			return attr->value;
	}

	return NULL;
}

static void
_getElementsByTagName(apr_array_header_t* arr, apr_xml_elem* n, char* tagname)
{
	if (!strcmp(n->name, tagname)) {
		*(const apr_xml_elem **)apr_array_push(arr) = n;
	}
	if (n->first_child) {
		_getElementsByTagName(arr, n->first_child, tagname);
	}
	if (n->next) {
		_getElementsByTagName(arr, n->next, tagname);
	}
}

apr_array_header_t*
getElementsByTagName(apr_pool_t* pool, apr_xml_doc* doc, char* tagname)
{
	if (NULL == doc || NULL == tagname || NULL == doc->root)
		return NULL;

	apr_array_header_t* arr = apr_array_make(pool, 1, sizeof(apr_xml_elem *));
	_getElementsByTagName(arr, doc->root, tagname);
	return arr;
}
